﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using irm.jsonUtils;
using irm.package;
using irm.utils;
using UnityEditor;
using UnityEngine;

namespace Editor.IRMPacker
{
    public class IRMPackWindow:EditorWindow
    {
        private Vector2 _size=new Vector2(500,200);

        private string _srcDirectoryPath=@"C:\Users\bjwbj\Desktop\Fiddler";
        private string _selectDir;
        private string _targetDirectoryPath=@"D:\web_root\mjgg\boxtime\puzzle_package";
        private string _packageName;
        private string _version="0.0";
        private string _rootPath;
        private void Awake()
        {
            minSize = _size;
            maxSize = _size;
            titleContent.text="IRMPacker";
            position=new Rect((Screen.width+_size.x)/2f,(Screen.height+_size.y)/2f,_size.x,_size.y);
            var dataPath = Application.dataPath;
            _rootPath =dataPath.Substring(0,dataPath.LastIndexOf("Assets"));
        }


        private void Update()
        {
            foreach (var o in Selection.assetGUIDs)
            {
                _selectDir=Path.Combine(_rootPath,AssetDatabase.GUIDToAssetPath(o));
                if (!string.IsNullOrEmpty(_selectDir))
                {
                    if(File.Exists(_selectDir)) _selectDir = Path.GetDirectoryName(_selectDir);
                    break;
                }
            }
        }

        void OnGUI()
        {
            GUILayout.Label("从Project中选择源文件夹", EditorStyles.boldLabel);
            _srcDirectoryPath = EditorGUILayout.TextField("文件夹", _selectDir);
            GUILayout.Label("输出文件夹", EditorStyles.boldLabel);
            _targetDirectoryPath= EditorGUILayout.TextField("文件夹", _targetDirectoryPath);
            _packageName= EditorGUILayout.TextField("包名", _packageName);
            _version= EditorGUILayout.TextField("版本号", _version);
            if (GUILayout.Button("打包"))
            {
                if(EditorUtility.DisplayDialog("提示",$"确定要打包?\n包名:{_packageName}\n版本:{_version}输出路径:{_targetDirectoryPath}","确定","取消"))
                {
                    if (string.IsNullOrEmpty(_srcDirectoryPath))
                    {
                        Alert("源文件夹不能为空");
                        return;
                    }

                    if (string.IsNullOrEmpty(_targetDirectoryPath))
                    {
                        Alert("目标文件夹不能为空");
                        return;
                    }

                    if (string.IsNullOrEmpty(_packageName))
                    {
                        Alert("包名不能为空");
                    }

                    if (string.IsNullOrEmpty(_version))
                    {
                        Alert("版本号不能为空");
                    }
                    else
                    {
                        var versionArray = _version.Split('.');
                        foreach (var s in versionArray)
                        {
                            try
                            {
                                int.Parse(s);
                            }
                            catch (Exception e)
                            {
                                Alert("版本号格式不正确:" + s);
                                return;
                            }
                        }
                    }
                    if (!Directory.Exists(_targetDirectoryPath))
                    {
                        if (Alert("目标文件夹不存在，点击确定创建？"))
                        {
                            Directory.CreateDirectory(_targetDirectoryPath);
                        }
                    }
                    Pack();
                }
            }
        }

        private bool Alert(string msg)
        {
            return EditorUtility.DisplayDialog("提示", msg, "确定","取消");
        }

        ////////////////////////////////////////////////////////

        private void Pack()
        {
            var manifest = new PackageManifest
            {
                Name = _packageName, Version = _version
            };
            var outputPackage = Path.Combine(_targetDirectoryPath, _packageName);
            var outputTarget = Path.Combine(outputPackage, _version);
            if (!Directory.Exists(outputPackage)) Directory.CreateDirectory(outputPackage);
            if(Directory.Exists(outputTarget))Directory.Delete(outputTarget,true);
            Directory.CreateDirectory(outputTarget);
            _srcDirectoryPath = _srcDirectoryPath.EndsWith("/") || _srcDirectoryPath.EndsWith("\\") ? _srcDirectoryPath : _srcDirectoryPath + "/";
            manifest.Size=GetFile(_srcDirectoryPath.Replace('\\','/'),_srcDirectoryPath, manifest.FileList);
            FileUtils.CopyDirectory(_srcDirectoryPath,outputTarget);
            var versionPath = Path.Combine(outputPackage, "version");
            File.WriteAllText(versionPath,_version);
            var manifestPath = Path.Combine(outputPackage, "manifest_"+_version);
            File.WriteAllText(manifestPath,JsonParser.ToJson(manifest));
            Debug.Log($"package {name} complete,total file count:{manifest.FileList.Count}");
        }
        private static long GetFile(string rootPath,string dirPath, Dictionary<string,PackageManifestInfo> list)
        {
            long totalSize = 0;
            var dirInfo=new DirectoryInfo(dirPath);
            foreach (var fileInfo in dirInfo.GetFiles())
            {
                var formattedPath = fileInfo.FullName.Replace('\\','/');
                formattedPath = formattedPath.Replace(rootPath, "");
                Debug.Log("relative path:"+formattedPath);
                totalSize += fileInfo.Length;
                var md5 = GetMD5HashFromFile(fileInfo.FullName);
                var info=new PackageManifestInfo();
                info.Path = formattedPath;
                info.Md5 = md5;
                info.Size = fileInfo.Length;
                list.Add(info.Path,info);
            }

            foreach (var directoryInfo in dirInfo.GetDirectories())
            {
                totalSize+=GetFile(rootPath,directoryInfo.FullName,list);
            }

            return totalSize;
        }
        private static string GetMD5HashFromFile(string fileName) {
            try {
                FileStream file = new FileStream(fileName, FileMode.Open);
                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] retVal = md5.ComputeHash(file);
                file.Close();

                var sb = new StringBuilder();
                for (int i = 0; i < retVal.Length; i++) 
                {
                    sb.Append(retVal[i].ToString("x2"));
                }
                return sb.ToString();
            } catch (Exception ex) {
                throw new Exception("GetMD5HashFromFile() fail,error:" + ex.Message);
            }
        }
    }
}